const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const session = require('koa-generic-session')
const redisStore = require('koa-redis')

const koaStatic = require('koa-static')
const path = require('path')

const { isProd } = require('./utils/env')
const { SESSION_SECRET_KEY } = require('./conf/secretKeys')

// 定义路由
const atAPIRouter = require('./routes/api/blog-at')
const squareAPIRouter = require('./routes/api/blog-square')
const profileAPIRouter = require('./routes/api/blog-profile')
const blogViewRouter = require('./routes/view/blog')
const homeAPIRouter = require('./routes/api/blog-home')
const userViewRouter = require('./routes/view/user')
const userAPIRouter = require('./routes/api/user')
const utilsAPIRouter = require('./routes/api/utils')
// 定义的时候顺序无所谓
const errorViewRouter = require('./routes/view/error')

// error handler  在页面显示的错误信息
let onerrorConf = {}
// 线上环境，提示跳转到首页，开发环境直接报出错误信息
if(isProd) {
    onerrorConf = {
        // 重定向到error路由
        redirect: '/error'
    }
}
onerror(app, onerrorConf)

// middlewares
// 下面两个是解析post请求携带的数据的(JSON格式)
app.use(bodyparser({
    enableTypes:['json', 'form', 'text']
}))
app.use(json())

// 日志
app.use(logger())
// 将public目录静态化
app.use(koaStatic(__dirname + '/public'))
// 把uploadFiles当作静态文件夹
app.use(koaStatic(path.join(__dirname, '..', 'uploadFiles')))
// 注册模板引擎
app.use(views(__dirname + '/views', {
    extension: 'ejs'
}))

// 设置密钥，加密uid
app.keys = [SESSION_SECRET_KEY]

// 引入redis配置
const { REDIS_CONF } = require('./conf/db')

// session配置
app.use(session({
    // cookie name，默认是koa.sid
    key: 'weibo.sid',   
    // redis key的前缀，默认是 koa:sess:，
    // 在执行redis.set的时候，会在key前面加前缀，显示是这个server的key（redis键的前缀）
    prefix: 'weibo:sess:',  
    cookie: {
        path: '/',
        // 只能在server端修改cookie
        httpOnly: true,
        // 过期时间：1天
        maxAge: 24 * 60 * 60 * 1000
    },
    // redis 也是这个时候过期（即cookie过期后，redis也会将内存中的session删除，用户需重新登录）
    ttl: 24 * 60 * 60 * 1000, // 默认和maxAge一致，可以不写
    // 将session存进redis中
    store: redisStore({
        all: `${REDIS_CONF.host}:${REDIS_CONF.port}`
    })
}))

// logger 中间件的演示，自己手写的打印日志的功能（其实上面已经封装了一个日志处理功能）
// app.use(async (ctx, next) => {
//   const start = new Date()
//   await next()
//   const ms = new Date() - start
//   console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
// })

// 使用（注册）路由
app.use(atAPIRouter.routes(), atAPIRouter.allowedMethods())
app.use(squareAPIRouter.routes(), squareAPIRouter.allowedMethods())
app.use(profileAPIRouter.routes(), profileAPIRouter.allowedMethods())
app.use(homeAPIRouter.routes(), homeAPIRouter.allowedMethods())
app.use(blogViewRouter.routes(), blogViewRouter.allowedMethods())
app.use(userViewRouter.routes(), userViewRouter.allowedMethods())
app.use(userAPIRouter.routes(), userAPIRouter.allowedMethods())
app.use(utilsAPIRouter.routes(), utilsAPIRouter.allowedMethods())
// error 和 404兜底，放在最下面
app.use(errorViewRouter.routes(), errorViewRouter.allowedMethods())

// error-handling 在后台打印的错误信息，上面的是在页面上显示的错误信息
app.on('error', (err, ctx) => {
    console.error('server error', err, ctx)
})

module.exports = app
